/*
*
*	The Gimme ECMAScript Library by Stephen Stchur
*	"Taking the pain out of Javascript!"
*
*	Copyright (c) Microsoft Corporation.  All rights reserved.
*
*	Description:
*	Gimme Screen Module:		Helper methods dealing with screen geometry (mouse position, scroll position, viewport size, etc...)
*	Gimme Screen Extensions:	g(..) extensions for retrieving DOM element position information
*
*	Requires:
*	gimme.query.js
*	gimme.object.js
*
*/

Gimme.Screen = new function()
{
	this.getViewportSize = function()
	{
		var size = { width: 0, height: 0 };
		if (typeof window.innerWidth !== 'undefined')
		{
			size = { width: window.innerWidth, height: window.innerHeight };
		}
		else if (typeof document.documentElement !== 'undefined' && typeof document.documentElement.clientWidth !== 'undefined' && document.documentElement.clientWidth !== 0)
		{
			size = { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight };
		}
		else
		{
			size = { width: document.getElementsByTagName('body')[0].clientWidth, height: document.getElementsByTagName('body')[0].clientHeight };
		}

		return size;
	};

	this.getMousePosition = function(_evt)
	{
		if (!_evt)
		{
			_evt = window.event;
		}

		var cursorPosition = { x: 0, y: 0 };

		// Standard way of obtaining cursor position relative to the entire page is via .pageX and .pageY.
		// IE-Mac has .pageX/Y but its value is wrong, so we check for a non-standard .x property (which IE-Mac doesn't have)
		// to ensure that that browser won't fall into this if block.
		if (typeof _evt.pageX !== 'undefined' && typeof _evt.x !== 'undefined')
		{
			cursorPosition.x = _evt.pageX;
			cursorPosition.y = _evt.pageY;
		}
		else
		{
			// The .clientX/Y properties measure the distance from the mouse cursor to the edges of the browser window.  In order to find the
			// mouse position relative to the entire page, we need to add scroll position to their values.
			// With the exception of Safari, the following is a cross-browser way of obtaining mouse position.  Safari incorrectly give .clientX/Y
			// the same value as .pageX/Y, which is why we need to use .pageX/Y above if it's available
			var scrollPosition = this.getScrollPosition();
			cursorPosition.x = _evt.clientX + scrollPosition.x;
			cursorPosition.y = _evt.clientY + scrollPosition.y;
		}

		return cursorPosition;
	};

	this.getScrollPosition = function()
	{
		var position = { x: 0, y: 0 };

		// window.pageYOffset is used by Firefox and Mozilla browsers, Safari, Opera, and Konqueror
		if (typeof window.pageYOffset !== 'undefined')
		{
			position.x = window.pageXOffset;	
			position.y = window.pageYOffset;
		}
		// document.documentElement.scrollTop is used by IE6 in standards-compliant mode
		else if (!Gimme.Browser.isInQuirksMode && typeof document.documentElement.scrollTop !== 'undefined')
		{
			position.x = document.documentElement.scrollLeft;
			position.y = document.documentElement.scrollTop;
		}
		// document.body.scrollTop is used by IE6 in "Quirks" mode
		else if (typeof document.body.scrollTop !== 'undefined')
		{
			position.x = document.body.scrollLeft;
			position.y = document.body.scrollTop;
		}

		return position;
	};
};

// Gimme Screen Extensions

// retrieves the absolute screen position of the nth element in the entities array (n defaults to 0)
Gimme.ext.getPosition = function(_accountForPageScroll, n)
{
	var elem = this.entities[n || 0]
	,useScroll
	,scrollPos
	,box
	,offset
	,xPos = 0
	,yPos = 0;

	if (!Gimme.Browser.isOpera && typeof elem.getBoundingClientRect !== 'undefined')
	{
		/*
		.getBoundingClientRect() returns a TextRectangle object whose coordinate values are relative to the client's
		upper-left corner.  In IE/Win5+, the window's upper-left is at 2,2 (pixels) with respect to the true client.
		See: http://msdn2.microsoft.com/en-us/library/ms536433.aspx
		
		Note however, that there are exceptions to the (2,2).  It seems that if the page is running within a frameset,
		the (2, 2) does not apply.  If it's running in a IFrame though, it still does.  What if it's running in a IFrame
		that's running in a Frameset?  No idea -- that kind of HTML should be illegal anyway.
		*/
		offset = !Gimme.Browser.isInIFrame && Gimme.Browser.isInFrameset ? 0 : 2;
		box = elem.getBoundingClientRect();
		xPos = box.left - offset;
		yPos = box.top - offset;
		
		/*
		In the case of .getBoundingClientRect(), the _accountForPageScroll bit needs to be interpreted backwards,
		because .getBoundingClientRect() already factors out page scroll and returns the screen position.  This is
		the exact opposite of what we do when manually calculating potision via the while loop below (that returns
		the page position by default, and so scroll position would have to be /subtracted/ out if screen position
		is desired.		
		*/
		if (!_accountForPageScroll)
		{
			scrollPos = Gimme.Screen.getScrollPosition();
			xPos += scrollPos.x;
			yPos += scrollPos.y;			
		}
		else
		{
			_accountForPageScroll = false;
		}
	}
	else
	{
		while (elem !== null)
		{
			useScroll = typeof elem.scrollTop !== 'undefined'
						&& elem !== document.body
						&& elem !== document.documentElement
						&& elem.tagName !== 'TEXTAREA'
						&& elem.tagName !== 'INPUT'
						? 1 : 0;
						
			xPos += elem.offsetLeft - (useScroll * elem.scrollLeft);
			yPos += elem.offsetTop - (useScroll * elem.scrollTop);
			elem = elem.offsetParent;
			
			if (elem && !Gimme.Browser.offsetIncludesBorders())
			{
				xPos += parseInt(g(elem).getStyle('borderLeftWidth')) || 0;
				yPos += parseInt(g(elem).getStyle('borderTopWidth')) || 0;
			}
		}
	}
	
	/*
	If screen position is desired, subtract out the window's horizontal and vertical scroll values
	from the current xPos and yPos values.
	*/
	if (_accountForPageScroll)
	{
		scrollPos = Gimme.Screen.getScrollPosition();
		xPos -= scrollPos.x;
		yPos -= scrollPos.y;
	}	
	
	return { x: xPos, y: yPos };
};

Gimme.ext.getScreenPosition = function(n)
{
	return this.getPosition(true, n);
};

Gimme.ext.getPagePosition = function(n)
{
	return this.getPosition(false, n);
};

// retrieves the relative position of the nth element in the entities array (n defaults to 0)
Gimme.ext.getComputedPosition = function(n)
{
	var elem = this.entities[n || 0];
	return { x: parseInt(g(elem).getStyle('left'), 10), y: parseInt(g(elem).getStyle('top'), 10) };
};

